﻿using System;
using System.Drawing;
using Microsoft.Office.Core;
using Microsoft.Office.Interop.PowerPoint;
using Shape = Microsoft.Office.Interop.PowerPoint.Shape;

namespace Microsoft.Office.PowerPoint.STAMP.Core
{
    /// <summary>
    /// A shape for displaying caption text.
    /// </summary>
    public class StampCaptionShape
    {
        private readonly Shape _shape;

        /// <summary>
        /// Initializes a new instance of the <see cref="StampCaptionShape"/> class.
        /// </summary>
        /// <param name="shape">The shape.</param>
        public StampCaptionShape(Shape shape)
        {
            _shape = shape;
        }

        /// <summary>
        /// Gets the internal id.
        /// </summary>
        public string InternalId
        {
            get { return _shape.Tags[CaptionShapeTags.CaptionInternalId]; }
        }

        /// <summary>
        /// Gets the name.
        /// </summary>
        public string Name
        {
            get { return _shape.Name; }
            set { _shape.Name = value; }
        }

        /// <summary>
        /// Gets the name of the exit book mark.
        /// </summary>
        public string BookMarkExitName
        {
            get { return _shape.Tags[CaptionShapeTags.BookMarkExitName]; }
        }

        /// <summary>
        /// Gets the name of the entry book mark.
        /// </summary>
        public string BookMarkEntryName
        {
            get { return _shape.Tags[CaptionShapeTags.BookMarkEntryName]; }
        }

        /// <summary>
        /// Gets or sets a value indicating whether this <see cref="StampCaptionShape"/> is visible.
        /// </summary>
        /// <value>
        ///   <c>true</c> if visible; otherwise, <c>false</c>.
        /// </value>
        public bool Visible
        {
            get { return _shape.Visible == MsoTriState.msoTrue ? true : false; }
            set { _shape.Visible = value ? MsoTriState.msoCTrue : MsoTriState.msoFalse; }
        }

        /// <summary>
        /// Applies the given styles to the shape.
        /// </summary>
        /// <param name="captionStyle">The caption style.</param>
        /// <param name="fontSize">Size of the font.</param>
        /// <param name="isHidden">if set to <c>true</c> [is hidden].</param>
        public void ApplyStyle(CaptionStyle captionStyle, float fontSize, bool isHidden)
        {
            _shape.TextFrame.TextRange.Font.Bold = captionStyle.FontStyle.HasFlag(FontStyle.Bold)
                                                       ? MsoTriState.msoTrue
                                                       : MsoTriState.msoFalse;
            _shape.TextFrame.TextRange.Font.Italic = captionStyle.FontStyle.HasFlag(FontStyle.Italic)
                                                         ? MsoTriState.msoTrue
                                                         : MsoTriState.msoFalse;
            _shape.TextFrame.TextRange.Font.Underline = captionStyle.FontStyle.HasFlag(FontStyle.Underline)
                                                            ? MsoTriState.msoTrue
                                                            : MsoTriState.msoFalse;
            _shape.TextFrame.TextRange.ParagraphFormat.Alignment = AlignmentConverter.ConvertToParagraphAlignment(captionStyle);

            _shape.TextFrame.TextRange.Font.Size = fontSize;
            _shape.TextFrame.TextRange.Font.Name = captionStyle.FontFamily.Name;

            _shape.TextFrame.TextRange.Font.Color.RGB = captionStyle.FontColorInteger;
            _shape.Fill.Solid();
            _shape.Fill.ForeColor.RGB = captionStyle.BackgroundColorInteger;

            _shape.TextFrame.MarginBottom = 0;
            _shape.TextFrame.MarginTop = 0;

            _shape.Visible = isHidden ? MsoTriState.msoFalse : MsoTriState.msoTrue;
        }

        /// <summary>
        /// Updates the size.
        /// </summary>
        /// <param name="position">The position.</param>
        public void UpdateSize(RectangleF position)
        {
            _shape.Left = position.Left;
            _shape.Top = position.Top;
            _shape.Width = position.Width;
            _shape.Height = position.Height;
        }

        /// <summary>
        /// Gets or sets the text.
        /// </summary>
        public string Text
        {
            get { return _shape.TextFrame.TextRange.Text; }
            set { _shape.TextFrame.TextRange.Text = value; }
        }

        /// <summary>
        /// Updates the tags.
        /// </summary>
        public void UpdateTags(string captionMediaId, CaptionItem caption)
        {
            UtilPowerPoint.SetShapeTag(_shape, MediaShapeTags.CaptionMediaId, captionMediaId);
            UtilPowerPoint.SetShapeTag(_shape, CaptionShapeTags.CaptionInternalId, caption.InternalId);
            UtilPowerPoint.SetShapeTag(_shape, CaptionShapeTags.CaptionItemSysName, caption.Name);
            UtilPowerPoint.SetShapeTag(_shape, CaptionShapeTags.BookMarkEntryName, caption.BookMarkEntryName);
            UtilPowerPoint.SetShapeTag(_shape, CaptionShapeTags.BookMarkExitName, caption.BookMarkExitName);
        }

        /// <summary>
        /// Gets the media id of this shape.
        /// </summary>
        public string MediaId
        {
            get { return _shape.Tags[MediaShapeTags.CaptionMediaId]; }
        }

        /// <summary>
        /// Adds entry and exit animations.
        /// </summary>
        /// <param name="sequence">The sequence.</param>
        /// <param name="mediaShape">The media shape.</param>
        public void AddAnimations(Sequence sequence, StampMediaShape mediaShape)
        {
            AddEntranceAnimation(sequence, mediaShape);
            AddExitAnimation(sequence, mediaShape);
        }

        private void AddEntranceAnimation(Sequence sequence, StampMediaShape mediaShape)
        {
            AddAnimation(mediaShape, BookMarkEntryName, false, sequence);
        }

        private void AddExitAnimation(Sequence sequence, StampMediaShape mediaShape)
        {
            AddAnimation(mediaShape, BookMarkExitName, true, sequence);
        }

        private void AddAnimation(StampMediaShape mediaShape, string bookmarkName, bool isExit, Sequence sequence)
        {
            Effect effect = sequence.AddTriggerEffect(
                _shape,
                MsoAnimEffect.msoAnimEffectFade,
                MsoAnimTriggerType.msoAnimTriggerOnMediaBookmark,
                mediaShape.Shape,
                bookmarkName);
            effect.Timing.TriggerType = MsoAnimTriggerType.msoAnimTriggerWithPrevious;
            if (isExit)
            {
                effect.Exit = MsoTriState.msoTrue;
            }
            effect.Timing.Duration = mediaShape.FadeDuration;
        }

        /// <summary>
        /// Deletes this instance.
        /// </summary>
        public void Delete()
        {
            _shape.Delete();
        }

        /// <summary>
        /// Updates the transparency.
        /// </summary>
        /// <param name="transparency">The transparency.</param>
        public void UpdateTransparency(float transparency)
        {
            _shape.Fill.Transparency = transparency;
        }
    }
}